package cn.enjoy.tool.juc.DataBaseConnect;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author K
 * @date 2021/7/29 下午4:07
 */
public class ConnectionPoolTest {
    /** 连接池大小 **/
    private static final int poolSize = 10;
    /** 线程数 **/
    private static final int threadCount = 100;
    /** 单线程连接次数 **/
    private static final int connectCount = 20;
    /** 尝试连接的duration **/
    private static final int waitMills = 1000;
    private static ConnectionPool connectionPool = new ConnectionPool(poolSize);
    private static CountDownLatch countDownLatch = new CountDownLatch(threadCount);
    static CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount);


    public static void main(String[] args) {
        AtomicInteger got = new AtomicInteger();
        AtomicInteger notGot = new AtomicInteger();

        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("数据库连接池").build();
        ExecutorService executorService = Executors.newCachedThreadPool(threadFactory);
        for (int i = 0; i < threadCount; i++) {
            ConnectionRunner connectionRunner = new ConnectionRunner(connectCount, got, notGot);
            executorService.execute(connectionRunner);
        }

        try {
            countDownLatch.await();
            executorService.shutdown();
            while (true) {
                if (executorService.isTerminated()) {
                    System.out.println("总连接次数：\t" + threadCount * connectCount);
                    System.out.println("已连接次数：\t" + got.get());
                    System.out.println("未连接次数：\t" + notGot.get());
                    break;
                } else {
                    Thread.sleep(2000);
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    static class ConnectionRunner implements Runnable {
        private int connectCount;
        private AtomicInteger got;
        private AtomicInteger notGot;

        public ConnectionRunner(int connectCount, AtomicInteger got, AtomicInteger notGot) {
            this.connectCount = connectCount;
            this.got = got;
            this.notGot = notGot;
        }

        @Override
        public void run() {
//            try {
//                cyclicBarrier.wait();
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }

            while (connectCount > 0) {
                try {
                    Connection connection = connectionPool.fetchConnection(waitMills);
                    if (connection != null) {
                        try {
                            connection.createStatement();
                            connection.commit();
                        } catch (SQLException e) {
                            e.printStackTrace();
                        } finally {
                            got.incrementAndGet();
                            connectionPool.releaseConnection(connection);
                        }
                    } else {
                        notGot.incrementAndGet();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    connectCount--;
                    countDownLatch.countDown();
                }
            }
        }
    }
}
